package edu.ecust.design.aspect;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import edu.ecust.design.annotation.DataModifyAuth;
import edu.ecust.design.cons.AccountLevel;
import edu.ecust.design.domain.Account;
import edu.ecust.design.domain.Log;
import edu.ecust.design.service.ILogService;
import edu.ecust.design.utils.AccountUtils;

@Aspect
@Component
public class SuppliersAspect {
	private static final Logger logger = Logger
			.getLogger(SuppliersAspect.class);
	@Autowired
	private ILogService logService;
	private final ObjectMapper objectMapper = new ObjectMapper();

	@Pointcut("execution (@edu.ecust.design.annotation.DataModifyAuth * * (..))")
	public void dataModifyAuth() {

	}

	@Around("dataModifyAuth()")
	public Object aroundAdvice(ProceedingJoinPoint pj) throws Throwable {
		Method method = getMethod(pj);
		Object[] objs = pj.getArgs();
		HttpServletRequest request = (HttpServletRequest) objs[0];
		Long accountId = null;
		if (request != null) {
			Account acc = AccountUtils.getAccountBySession(request);
			accountId = acc.getId();
			int level = acc.getUserType();
			if (level != AccountLevel.normal.getId()) {
				pj.proceed();
			}
		}
		DataModifyAuth dataModifyAuth = AnnotationUtils.findAnnotation(method,
				DataModifyAuth.class);
		String opName = dataModifyAuth.op();
		recordLog(opName, request.getRequestURI(), getParamsString(objs),
				accountId);
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("success", false);
		m.put("message", "没有授权，不能进行该操作");
		return write(m);
	}

	/**
	 * 获取所有参数
	 * 
	 * @param objs
	 * @return
	 */
	private String getParamsString(Object[] objs) {
		if (objs == null) {
			return null;
		}
		if (objs.length == 0) {
			return null;
		}
		StringBuffer buff = new StringBuffer("params:");
		for (Object o : objs) {
			buff.append(o.toString());
			buff.append(",");
		}
		String params = buff.toString();
		return params.substring(0, params.length() - 1);
	}

	/**
	 * 日志记录
	 * 
	 * @param opName
	 * @param appPath
	 * @param params
	 * @param accountId
	 */
	private void recordLog(String opName, String appPath, String params,
			Long accountId) {
		Log log = new Log();
		log.setAppPath(appPath);
		log.setOpName(opName);
		log.setOpUser(accountId);
		log.setParams(params);
		logService.recordOperatLog(log);
	}

	private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
		Signature sig = jp.getSignature();
		MethodSignature msig = (MethodSignature) sig;
		return getClass(jp).getMethod(msig.getName(), msig.getParameterTypes());
	}

	private Class<? extends Object> getClass(JoinPoint jp)
			throws NoSuchMethodException {
		return jp.getTarget().getClass();
	}

	private String write(Object o) {
		try {
			return objectMapper.writeValueAsString(o);
		} catch (JsonGenerationException e) {
			logger.error(e);
		} catch (JsonMappingException e) {
			logger.error(e);
		} catch (IOException e) {
			logger.error(e);
		}
		return null;
	}
}
